<?php
//provide an useful function to simplify the multiple level data
namespace app\common\model;

trait TreeBase
{

	/**
	 * this is the parameter for the trait, you could define it in your derive class,
	 * if you define this field, the function will choice the right function to execute the operate,
	 * if you ignore this field,the function will do according to its definition.
	 * the field value could be set to "multi" or "single"
	 * you have to define the field below by yourself.
	 */
	//protected $treeType;



	/**
	 * make the data into a tree,which has the $pid_key as primary key
	 *
	 * multiple root tree
	 * @param Array $data the data to deal
	 * @param string $pid_key the parent id name
	 * @param string $pk the primary key name of the element
	 *
	 * @return Array a tree create by data,this function will delete the invalid item
	 */
	public function makeTrees($data,$pid_key='pid',$pk='id'){
		if (isset($this->treeType) && $this->treeType=='single')
			return $this->makeTree($data,$pid_key,$pk);

		$root=[];
		$tmp=[];
		$data_tmp=[0=>['child'=>[],'id'=>0,'pid'=>-1]];
		foreach ($data as $d) {
			$d['child']=null;
			$data_tmp[$d[$pk]]=$d;
		}

		foreach ($data_tmp as &$v) {
			//it is a child element
			if (isset($data_tmp[$v[$pid_key]])){
				//parent exist.
				$parent=&$data_tmp[$v[$pid_key]];
				if (!$parent['child'])
					$parent['child']=[];
				$parent['child'][count($parent['child'])]=&$v;
			}
		}

		unset($data_tmp[0]);
		foreach ($data_tmp as &$v) {
			if (!isset($v['child']))
				continue;
			$this->_treeDelete($data_tmp,$v['child'],$pk);
		}

		return array_merge($data_tmp);
	}

	protected function _treeDelete(&$array,&$current,$pk='id',$depth=0) {
		if ($depth>10)
			return;
		foreach ($current as $v) {
			if (isset($v['child']))
				$this->_treeDelete($array,$v['child'],$pk,$depth+1);
			unset($array[$v[$pk]]);
		}
	}

	/**
	 * make the data into a tree,which has the $pid_key as primary key
	 * single root version
	 *
	 * @param Array $data the data to deal
	 * @param string $pid_key the parent id name
	 * @param string $pk the primary key name of the element
	 *
	 * @return Array a tree create by data,this function will delete the invalid item
	 */
	public function makeTree($data,$pid_key='pid',$pk='id'){
		if (isset($this->treeType)&&$this->treeType=='multi')
			return $this->makeTrees($data,$pid_key,$pk);
		$root=[];
		$tmp=[];
		$data_tmp=[0=>['child'=>[],'id'=>0,'pid'=>-1]];
		foreach ($data as $d){
			$d['child']=null;
			$data_tmp[$d[$pk]]=$d;
		}

		foreach ($data_tmp as &$v){
			//it is a child element
			if (isset($data_tmp[$v[$pid_key]])){
				//parent exist.
				$parent=&$data_tmp[$v[$pid_key]];
				if (!$parent['child'])
					$parent['child']=[];
				$parent['child'][count($parent['child'])]=&$v;
			}
		}
		return $data_tmp[0]['child'];
	}
}



?>